#include "lua_service.h"
#include "message_service.h"
#include "game_thread.h"
#include "c_msg.h"
#include "script_msg.h"
#include "service_mgr.h"

LuaService::LuaService() : luaVm_(NULL) {
	registerMsgHandle(reqRemoteScriptCall);
	registerMsgHandle(reqRetCoroutine);
	registerMsgHandle(reqKickService);
	registerMsgHandle(retFinalSaveOk);
}

void LuaService::onAllocThread(Thread* thread) {
	GameThread* gameThread = dynamic_cast<GameThread*>(thread);
	shengine_assert(gameThread);
	if (gameThread) {
		shengine_assert(gameThread->getLuaVm());
		setLuaVm(gameThread->getLuaVm());
	}
}

void LuaService::onRemoveFromThread() {
	CMessage msg("reqRemoveService");
	msg << getHandle();
	gMessageMgr.sendMessage(gServiceMgr.getHandle(), msg.msg());
	setLuaVm(NULL);
}

void LuaService::processFrame() {
	scriptCall("process");
}

bool LuaService::handleMessage(uint8 funcType, const char* funcName, StreamReader& params) {
	if (!super::handleMessage(funcType, funcName, params)) {
		if (funcType == MSG_TLUA) {
			StreamWriter rets;
			luaVm_->callEx(funcName, &params, &rets);
			return true;
		}
	}
	return true;
}

bool LuaService::scriptCall(const char* f, StreamReader* params, StreamWriter* rets) {
	return scriptEngine()->callModule(entryFunc_.c_str(), luaClass_.c_str(), getHandle(), f, params, rets);
}

bool LuaService::scriptCallEx(const char* f, StreamReader* params, StreamWriter* rets) {
	return scriptEngine()->callModuleEx(entryFunc_.c_str(), luaClass_.c_str(), getHandle(), f, params, rets);
}

bool LuaService::scriptCallRaw(const char* f, StreamReader* params, StreamWriter* rets) {
	return scriptEngine()->call(f, params, rets);
}

bool LuaService::scriptCallRawEx(const char* f, StreamReader* params, StreamWriter* rets) {
	return scriptEngine()->callEx(f, params, rets);
}

void LuaService::start() {
	scriptCall("start");
}

bool LuaService::finalsave() {
	if (state_ == SERVICE_STATE_EXITING) {
		ScriptRets rets;
		bool ret = scriptCall("finalsave", NULL, &rets);
		if (ret) {
			StreamReader reader = rets.createStreamReader();
			uint8 ret_num;
			reader >> ret_num >> ret;
			return ret_num > 0 && ret;
		}
		else {
			printf("==>>Error: Service[%s] handle[%llu] finalsave failed !\n", getName().c_str(), getHandle().getValue());
			return true;
		}
	}
	else {
		shengine_assert(0);
	}
	return false;
}

void LuaService::reqRemoteScriptCall(LuaService& self, StreamReader& params) {
	uint64 retHandle;
	uint64 coid;
	uint64 targetHandle;
	const char* fName;
	params >> retHandle >> coid >> targetHandle >> fName;
	ScriptRets rets;
	self.scriptCallEx(fName, &params, &rets);

	if (coid != -1) {
		CMessage msg("reqRetCoroutine");
		if (rets.length() > 0) {
			uint8 ret_num = rets.data()[0];
			msg << (uint8)(ret_num + 1);
			msg << (uint8)MSGPARAM_TINTEGER;
			msg << coid;
			msg.appenBuffer(rets.data() + sizeof(uint8), rets.length() - sizeof(uint8));
		}
		else {
			msg << (uint8)1;
			msg << (uint8)MSGPARAM_TINTEGER;
			msg << coid;
		}
		gMessageMgr.sendMessage(retHandle, msg.msg());
	}
}

void LuaService::reqRetCoroutine(LuaService& self, StreamReader& params) {
	self.scriptCall("ret_coroutine", &params);
}

void LuaService::reqKickService(LuaService& self, StreamReader& params) {
	self.kickme();
}

void LuaService::retFinalSaveOk(LuaService& self, StreamReader& params) {
	self.stopok();
}
